package com.open.demo.协程

import android.os.Bundle
import android.util.Log
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import com.open.demo.R
import com.open.demo.utils.Constats
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.selects.select
import java.lang.ArithmeticException

class CoroutineTestActivity : AppCompatActivity() {

    companion object {
        const val TAG = "协程 Demo"
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_coroutine)
        launchTest1()
        launchTest2()
        launchTest3()
        initFlow()

        lauchTimeOut()
    }

    private fun initFlow() {
        GlobalScope.launch {
            val localDeferred = async {

            }
            val userResponse = select<Int> {
                localDeferred.onAwait{
                    1
                }
            }
        }

        val intFlow = flow<Int> {
            (1..3).forEach {
                emit(it)
                delay(100)
            }
        }.onEach { println("initFlow ${it}") }.launchIn(GlobalScope)

//        GlobalScope.launch(Dispatchers.Main) {
//            intFlow.flowOn(Dispatchers.IO).collect {
//                println(it)
//            }
//        }.join()

        flow<Int> {
            emit(1)
            throw  ArithmeticException("Div 0")
        }.catch { t:Throwable->
            println("caught error:$t")
        }

    }

    private fun launchTest1() {
        GlobalScope.launch(Dispatchers.Main) {
            val result = getUserSusped("hailong.qiu")
            Log.d(Constats.TAG, "getUserSusped result:$result")
            val textview = findViewById<TextView>(R.id.textview)
            textview.text = "result:$result"
        }

        Log.d(Constats.TAG,"GlobalScope launch start")
        GlobalScope.launch {
            delay(3888)
            Log.d(Constats.TAG,"GlobalScope launch call")
        }
        Log.d(Constats.TAG,"GlobalScope launch end")

        GlobalScope.async {

        }

        Log.d(Constats.TAG,"runBlocking start")
        runBlocking {
            delay(3000)
            print("runBlocking")
        }
        Log.d(Constats.TAG, "runBlocking end")
    }

    private fun launchTest2() {
        Log.d(Constats.TAG, "launchTest2 start")
        val job = CoroutineScope(Dispatchers.IO).launch {
            delay(1000)
            Log.d(Constats.TAG, "launchTest2 call")
        }
        Log.d(Constats.TAG, "launchTest2 end")
    }

    private fun launchTest3() {
        Log.d(Constats.TAG, "launchTest3 start")
        GlobalScope.launch {
            delay(1000)
            Log.d(Constats.TAG, "launchTest3 GlobalScope.launch")
            launch {
                delay(1000)
                Log.d(Constats.TAG, "launchTest3 GlobalScope.launch launch 子协程")
            }
        }
        Log.d(Constats.TAG, "launchTest3 end")
    }

    private fun launchTimeOut() {
        GlobalScope.launch {
            val userDeferred = async {

            }

            val timeoutJob = launch {
                delay(5000)
                userDeferred.cancel()
            }

            val user = userDeferred.await()
            timeoutJob.cancel()

        }
    }

    val channel = Channel<Int>()

    private fun lunchChannel() {
        var producer = GlobalScope.launch {
            var i = 0
            while (true) {
                delay(1000)
                channel.send(i++)
            }
        }
    }

    fun lauchTimeOut() {
        GlobalScope.launch {
            val userDeferred = async {
                delay(3000)
                "hailong.qiu"
            }

            val timeoutJob = launch {
                delay(5000)
                userDeferred.cancel()
            }
            Log.d(TAG, "lauchTimeOut start")
            val user = userDeferred.await()
            timeoutJob.cancel()
            Log.d(TAG, "lauchTimeOut user:$user")
        }
    }

}

fun GlobalScope.ioSync(timeMillis: Long=10000, cb:()->Int) {
    GlobalScope.launch {
        val userDeferred = async {
            cb()
            delay(3000)
            "hailong.qiu"
        }

        val timeoutJob = launch {
            delay(timeMillis)
            userDeferred.cancel()
        }

        Log.d(CoroutineTestActivity.TAG, "lauchTimeOut start")
        val user = userDeferred.await()
        timeoutJob.cancel()
        Log.d(CoroutineTestActivity.TAG, "lauchTimeOut user:$user")
    }
}